package com.ycy.diagram;

import com.ycy.BaseTest;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.BpmnAutoLayout;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.junit.Test;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;

public class

Diagram extends BaseTest {

  @Test
  public void createDef() {
    RepositoryService repositoryService = processEngine.getRepositoryService();
//    Deployment deploy = repositoryService.createDeployment().addClasspathResource("dynamic/easy_key.bpmn20.xml").deploy();
    Deployment deploy = repositoryService.createDeployment().addClasspathResource("dynamic/revert_key.bpmn20.xml").deploy();
    System.out.println(deploy.getId());
  }

  @Test
  public void creatProcInst() {
    RuntimeService runtimeService = processEngine.getRuntimeService();
    HashMap<String, Object> variables = new HashMap<>();
    List<String> zhixingrens = new ArrayList<>();
    zhixingrens.add("ycy");
    zhixingrens.add("xdm");
    variables.put("ASSIGNEE_zx1_LIST", zhixingrens);
//    ProcessInstance processInstance =
//            runtimeService.startProcessInstanceByKey("easy_key_1", variables);
    ProcessInstance processInstance =
            runtimeService.startProcessInstanceByKey("revert_key", variables);
    System.out.println(processInstance.getProcessInstanceId());
  }

  @Test
  public void d() {
    String processDefId = "easy_key:1:4";
    BpmnModel bpmnModel = processEngine.getRepositoryService().getBpmnModel(processDefId);
    // GraphicInfo 是图的信息
    GraphicInfo start = bpmnModel.getGraphicInfo("fq");
    System.out.println(start);

  }

  @Test
  public void dd() {
    String processId = "90001";
    ProcessInstance pi = processEngine.getRuntimeService().createProcessInstanceQuery().processInstanceId(processId).singleResult();
    //获取流程图
    BpmnModel bpmnModel = processEngine.getRepositoryService().getBpmnModel(pi.getProcessDefinitionId());

    modifyBpmnModel(bpmnModel);

  }

  @Test
  public void query() {
    List<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery().list();
    for (ProcessDefinition processDefinition : list) {
      System.out.println(processDefinition);
    }
  }

  @Test
  public void test() {
//    BpmnModel bpmnModel = processEngine.getRepositoryService().getBpmnModel(flowableTask.getProcessDefinitionId());
//    Process process = bpmnModel.getMainProcess();
//    FlowElement flowElement = process.getFlowElementMap().get(taskDefinitionId);
//    MultiInstanceLoopCharacteristics loopCharacteristics = ((UserTask) flowElement).getLoopCharacteristics();
//    String completionCondition = loopCharacteristics.getCompletionCondition();
//    RepositoryService repositoryService = processEngine.getRepositoryService();
//    repositoryService.ser
  }

  public static final String REVERT_EXCLUSIVEGATEWAY_SUFFIX = "_revertexclusivegateway";

  public void modifyBpmnModel(BpmnModel bpmnModel) {

    List<Process> processes = bpmnModel.getProcesses();
    Process process = processes.get(0);
    Collection<FlowElement> flowElements = process.getFlowElements();

    //获取驳回网关
    List<FlowElement> revertexclusivegateways = new LinkedList<>();
    for (FlowElement flowElement : flowElements) {
      if (flowElement.getId().endsWith(REVERT_EXCLUSIVEGATEWAY_SUFFIX) && flowElement instanceof ExclusiveGateway) {
        System.out.println(flowElement);
        revertexclusivegateways.add(flowElement);
      }
    }

    for (FlowElement revertexclusivegateway : revertexclusivegateways) {
      List<SequenceFlow> incomingFlows = ((ExclusiveGateway) revertexclusivegateway).getIncomingFlows();
      List<SequenceFlow> outgoingFlows = ((ExclusiveGateway) revertexclusivegateway).getOutgoingFlows();
      //获取进线
      SequenceFlow incomingSequenceFlow = incomingFlows.get(0);
      String sourceRef = incomingSequenceFlow.getSourceRef();
      //删除出线
      String targetRef = null;
      String passSkipExpression = "${" + String.format(COND_USERTASK_VAR_EXPRESSION_PASS + "}", sourceRef);
      for (SequenceFlow outgoingFlow : outgoingFlows) {
        process.removeFlowElement(outgoingFlow.getId());
        String skipExpression = outgoingFlow.getConditionExpression();
        if (StringUtils.equals(passSkipExpression, skipExpression)) {
          targetRef = outgoingFlow.getTargetRef();
        }
      }
      //修改进线
      incomingSequenceFlow.setId(sourceRef + "-" + targetRef);
      incomingSequenceFlow.setTargetRef(targetRef);
      //删除驳回网关
      process.removeFlowElement(revertexclusivegateway.getId());
    }

    //重新生成图GraphicInfo
    new BpmnAutoLayout(bpmnModel).execute();
  }

  public static final String COND_USERTASK_VAR_EXPRESSION_PASS = "COND_%1$s_approve/COND_%1$s_nrOfCompletedInstances>=0.5";

  @Test
  public void test111() {
    String format = String.format(COND_USERTASK_VAR_EXPRESSION_PASS, 1);
    System.out.println(format);
  }

  /**
   * 生成流程图
   */
  @Test
  public void genProcessDiagram() throws IOException {
    String processId = "102501";
    ProcessInstance pi = processEngine.getRuntimeService().createProcessInstanceQuery().processInstanceId(processId).singleResult();
    //流程走完的不显示图
    if (pi == null) {
      return;
    }

    List<HistoricActivityInstance> historyProcess = getHistoryProcess(processId);
    List<String> activityIds = new ArrayList<>();
    List<String> flows = new ArrayList<>();

    for (HistoricActivityInstance hi : historyProcess) {
      String activityType = hi.getActivityType();
      if (activityType.equals("sequenceFlow") || activityType.equals("exclusiveGateway")) {
        flows.add(hi.getActivityId());
      } else if (activityType.equals("userTask") || activityType.equals("startEvent")) {
        activityIds.add(hi.getActivityId());
      }
    }


    ProcessEngineConfiguration engConf = processEngine.getProcessEngineConfiguration();
    //定义流程画布生成器
    ProcessDiagramGenerator processDiagramGenerator = engConf.getProcessDiagramGenerator();


//    //4. 获取流程定义的所有节点信息
//    List<FlowNode> flowNodes = .findFlowNodes(pi.getProcessDefinitionId());
//    Map<String, FlowNode> activityMap = flowNodes.stream().collect(Collectors.toMap(FlowNode::getId, flowNode -> flowNode));
//    List<String> highLightedFlows = new ArrayList<>();
//
//    //5. 递归得到高亮线
//    activeActivityIds.forEach(activeActivityId -> this.getHighLightedFlows(activityMap, hisActivityMap, activeActivityId, highLightedFlows, activeActivityId));

    //获取流程图
    BpmnModel bpmnModel = processEngine.getRepositoryService().getBpmnModel(pi.getProcessDefinitionId());

    modifyBpmnModel(bpmnModel);

    Process process = bpmnModel.getProcesses().get(0);
    for (FlowElement flowElement : process.getFlowElements()) {
      System.out.println(flowElement);
    }

    InputStream in = processDiagramGenerator.generateDiagram(bpmnModel, "jpg", activityIds, flows, true);
    OutputStream out = null;
    byte[] buf = new byte[1024];
    int legth = 0;
    try {
//      out = httpServletResponse.getOutputStream();
      out = new FileOutputStream("/Users/ycy/Desktop/linshi/h1.jpg");
      while ((legth = in.read(buf)) != -1) {
        out.write(buf, 0, legth);
      }
    } finally {
      if (in != null) {
        in.close();
      }
      if (out != null) {
        out.close();
      }
    }


  }

  /**
   * 任务历史
   *
   * @param processId 部署id
   */
  /**
   * 任务历史
   *
   * @param processId 部署id
   */
  public List<HistoricActivityInstance> getHistoryProcess(String processId) {
    List<HistoricActivityInstance> list = processEngine.getHistoryService() // 历史相关Service
            .createHistoricActivityInstanceQuery() // 创建历史活动实例查询
            .processInstanceId(processId) // 执行流程实例id
            .finished()
            .list();
    return list;
  }


  private void getHighLightedFlows(Map<String, FlowNode> flowNodeMap,
                                   Map<String, HistoricActivityInstance> hisActivityMap,
                                   String activeActivityId,
                                   List<String> highLightedFlows,
                                   String oldActivityId) {
    FlowNode flowNode = flowNodeMap.get(activeActivityId);
    List<SequenceFlow> incomingFlows = flowNode.getIncomingFlows();
    for (SequenceFlow sequenceFlow : incomingFlows) {
      String sourceRefId = sequenceFlow.getSourceRef();
      if (hisActivityMap.containsKey(sourceRefId) && !oldActivityId.equals(sourceRefId)) {
        highLightedFlows.add(sequenceFlow.getId());
        this.getHighLightedFlows(flowNodeMap, hisActivityMap, sourceRefId, highLightedFlows, oldActivityId);
      } else {
        if (hisActivityMap.containsKey(sourceRefId)) {
          highLightedFlows.add(sequenceFlow.getId());
        }
        break;
      }
    }
  }


}
